﻿Imports Zytonic_Framework.Extentions.FileInfoExtentions

Public Class PinControl

#Region "Behavior"
    Private Enabled As Boolean = True
    Private HoverTimer As New Zytonic_Framework.Utilities.Timers.IntervalTimer(100, False)
    Private HoldTimer As New Zytonic_Framework.Utilities.Timers.IntervalTimer(100, False)
    Private InfoWindow As InformationWindow
    Private Sub userControl_PreviewDragEnter(sender As Object, e As DragEventArgs) Handles userControl.PreviewDragEnter
        If e.Data.GetDataPresent(DataFormats.FileDrop) Then
            e.Effects = Windows.DragDropEffects.Copy
        End If
    End Sub

    Private Sub PinControl_MouseEnter(sender As Object, e As MouseEventArgs) Handles Me.MouseEnter
        If Not Enabled Then Return
        HoverTimer = New Zytonic_Framework.Utilities.Timers.IntervalTimer(100, False)
        Dim Ticks As Integer = 0
        AddHandler HoverTimer.Tick, _
            Sub()
                If Ticks >= 7 Then
                    Dispatcher.Invoke( _
                        Sub()
                            If Not Enabled Then Return
                            If InfoWindow IsNot Nothing Then InfoWindow = Nothing
                            Dim locationFromWindow As Point = MyProperties.DockWindow.TranslatePoint(New Point(0, 0), MyProperties.DockWindow)
                            Dim locationFromScreen As Point = Me.PointToScreen(locationFromWindow)
                            InfoWindow = New InformationWindow(PinData.Filename, locationFromScreen.Y)
                            InfoWindow.Show()
                        End Sub)
                    HoverTimer.Enabled = False
                End If
                Ticks += 1
            End Sub
        HoverTimer.Enabled = True
    End Sub

    Private Sub PinControl_MouseLeave(sender As Object, e As MouseEventArgs) Handles Me.MouseLeave
        If InfoWindow IsNot Nothing Then
            If InfoWindow.IsVisible Then InfoWindow.ClosingStoryboard.Begin()
        End If

        HoverTimer.Enabled = False
    End Sub

    Private Sub PinControl_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown
        If Not Enabled Then Return
        HoldTimer = New Zytonic_Framework.Utilities.Timers.IntervalTimer(100, False)
        Dim Ticks As Integer = 0
        AddHandler HoldTimer.Tick, _
            Sub()
                If Ticks >= 7 Then
                    Dispatcher.Invoke( _
                        Sub()
                            ' TODO: Add hold event

                        End Sub)
                    HoldTimer.Enabled = False
                End If
                Ticks += 1
            End Sub
        HoldTimer.Enabled = True
    End Sub

    Private Sub userControl_PreviewDrop(sender As Object, e As DragEventArgs) Handles userControl.PreviewDrop
        If e.Data.GetDataPresent(DataFormats.FileDrop) Then
            Dim files As String() = e.Data.GetData(DataFormats.FileDrop)
            Dim Args As String = """" & String.Join(""" """, files) & """"

            Select Case IO.Path.GetExtension(PinData.Filename).ToLower
                Case ".appref-ms"
                    Dim Shell = New Shell32.Shell()
                    Dim Directory As Shell32.Folder = Shell.NameSpace(System.IO.Path.GetDirectoryName(PinData.Filename))
                    Dim ShortcutFile As Shell32.FolderItem = Directory.Items.Item(System.IO.Path.GetFileName(PinData.Filename))
                    Dim Shortcut As Shell32.ShellLinkObject = DirectCast(ShortcutFile.GetLink, Shell32.ShellLinkObject)

                    Dim P As New Process() With {.StartInfo = New ProcessStartInfo(Shortcut.Target.Path) With {.Arguments = Args}}
                    P.Start()
                Case Else
                    Dim P As New Process() With {.StartInfo = New ProcessStartInfo(PinData.Filename) With {.Arguments = Args}}
                    P.Start()
            End Select
           
        End If
    End Sub

    Private Sub PinControl_MouseRightButtonDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseRightButtonDown
        Dim Items As New Dictionary(Of String, Action)
        Items.Add("Properties", New Action(Sub()
                                               Dim Settings As New SettingsWindow(Me)
                                               Settings.ShowDialog()
                                           End Sub))
        Items.Add("Remove Pin", New Action(Sub()
                                               Enabled = False
                                               If HoverTimer IsNot Nothing Then
                                                   HoverTimer.Enabled = False
                                                   HoverTimer = Nothing
                                               End If

                                               If HoldTimer IsNot Nothing Then
                                                   HoldTimer.Enabled = False
                                                   HoldTimer = Nothing
                                               End If

                                               Properties.RemovePin(PinData)
                                               MyProperties.DockWindow.PinStackPanel.Children.Remove(Me)
                                           End Sub))
        Enabled = False
        Dim locationFromWindow As Point = MyProperties.DockWindow.TranslatePoint(New Point(0, 0), MyProperties.DockWindow)
        Dim locationFromScreen As Point = Me.PointToScreen(locationFromWindow)
        Dim InfoWindow As New InformationWindow(PinData.Filename, locationFromScreen.Y)

        InfoWindow.Show()
        Dim ContextMenu As New ContextMenuWindow(Items, New Point(InfoWindow.Left + 22, locationFromScreen.Y + InfoWindow.Height - 35), InfoWindow)
        AddHandler ContextMenu.Closed, _
            Sub()
                InfoWindow.ClosingStoryboard.Begin() : Enabled = True
            End Sub

        ContextMenu.ShowDialog()
    End Sub

    Private Sub PinControl_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseDoubleClick
        Process.Start(PinData.Filename, PinData.Arguments)
    End Sub

#End Region

    Public ReadOnly Property PinData As PinData
        Get
            Return _PinData
        End Get
    End Property
    Private _PinData As PinData

    Public Sub New(Filename As String)
        InitializeComponent()

        Me._PinData = New PinData(Filename)

        Dim BI As New BitmapImage
        BI.BeginInit()
        BI.CacheOption = BitmapCacheOption.None
        BI.UriSource = New Uri(PinData.CachedIconFilename, UriKind.RelativeOrAbsolute)
        BI.EndInit()

        MainImage.Source = BI
    End Sub

    Public Sub New(Data As PinData)
        InitializeComponent()
        Me._PinData = Data
        Dim BI As New BitmapImage
        BI.BeginInit()
        BI.CacheOption = BitmapCacheOption.None
        BI.UriSource = New Uri(PinData.CachedIconFilename, UriKind.RelativeOrAbsolute)
        BI.EndInit()

        MainImage.Source = BI
    End Sub

End Class

<Serializable> _
Public Class PinData

#Region "Properties"
    Public Property Filename As String
    Public Property Arguments As String
    Public Property CachedIconFilename As String
#End Region

    Public Sub New(Filename As String)
        Dim IconCache As String = IO.Path.Combine({My.Computer.FileSystem.SpecialDirectories.Temp, "iconCache"})

        Dim CacheDirectory As New IO.DirectoryInfo(IconCache)
        If Not CacheDirectory.Exists Then
            CacheDirectory.Create()
        End If

        Dim ImageExtentions As String() = {".png", ".bmp", ".jpg", ".gif", ".tif"}
        Dim FileExtention As String = IO.Path.GetExtension(Filename).ToLower

        Me.Filename = Filename

        Dim CachedIcon As String = IO.Path.Combine({IconCache, IO.Path.GetFileNameWithoutExtension(Filename) & FileExtention & ".png"})
        Dim CachedFile As New IO.FileInfo(CachedIcon), FileInf As New IO.FileInfo(Filename)

        If FileInf.isDirectory Then
            CachedIcon = "/Go Gadget;component/Resources/Folder.png"
        ElseIf Not CachedFile.Exists Then
            If FileExtention = ".exe" Then
                Try
                    ExtractIcon(Filename, CachedIcon)
                Catch ex As Exception
                    'Use Default Icon
                    CachedIcon = "/Go Gadget;component/Resources/Exe.png"
                End Try
            ElseIf FileExtention = ".appref-ms" Then
                Dim Shell = New Shell32.Shell()
                Dim Directory As Shell32.Folder = Shell.NameSpace(System.IO.Path.GetDirectoryName(Filename))
                Dim ShortcutFile As Shell32.FolderItem = Directory.Items.Item(System.IO.Path.GetFileName(Filename))
                Dim Shortcut As Shell32.ShellLinkObject = DirectCast(ShortcutFile.GetLink, Shell32.ShellLinkObject)

                CachedIcon = IO.Path.Combine({IconCache, IO.Path.GetFileNameWithoutExtension(Shortcut.Target.Path) & FileExtention & ".png"})
                Try
                    ExtractIcon(Shortcut.Target.Path, CachedIcon)
                Catch ex As Exception
                    'Use Default Icon
                    CachedIcon = "/Go Gadget;component/Resources/Exe.png"
                End Try
            ElseIf FileExtention = ".lnk" Then
                Dim Shell = New Shell32.Shell()
                Dim Directory As Shell32.Folder = Shell.NameSpace(System.IO.Path.GetDirectoryName(Filename))
                Dim ShortcutFile As Shell32.FolderItem = Directory.Items.Item(System.IO.Path.GetFileName(Filename))
                Dim Shortcut As Shell32.ShellLinkObject = DirectCast(ShortcutFile.GetLink, Shell32.ShellLinkObject)

                Me.Arguments = Shortcut.Arguments

                Me.Filename = Shortcut.Target.Path
                FileExtention = IO.Path.GetExtension(Me.Filename).ToLower
                CachedIcon = IO.Path.Combine({IconCache, IO.Path.GetFileNameWithoutExtension(Me.Filename) & FileExtention & ".png"})
                Try
                    ExtractIcon(Shortcut.Target.Path, CachedIcon)
                Catch ex As Exception
                    'Use Default Icon
                    CachedIcon = "/Go Gadget;component/Resources/Exe.png"
                End Try
            ElseIf ImageExtentions.Contains(FileExtention) Then
                'Create Small Thumbnail
                Using Image As New System.Drawing.Bitmap(Filename)
                    Using Thumb As System.Drawing.Bitmap = Image.CreateSquareThumb(32)
                        Thumb.Save(CachedIcon)
                    End Using
                End Using
            End If
        End If

        Me.CachedIconFilename = CachedIcon

    End Sub

    Private Sub ExtractIcon(TargetApplication As String, OutputPath As String)
        If IO.File.Exists(OutputPath) Then Return
        Dim MS As New IO.FileStream(OutputPath, IO.FileMode.CreateNew)
        Dim Icons As New IconExtractor(TargetApplication)

        'Find Biggest Icon
        Dim BiggestIcon As System.Drawing.Icon = Icons.GetIcon(0)
        For i As Integer = 1 To Icons.IconCount - 1
            Dim Icon As System.Drawing.Icon = Icons.GetIcon(i)
            If (Icon.Size.Width * Icon.Size.Height) > (BiggestIcon.Size.Height * BiggestIcon.Size.Width) Then
                BiggestIcon = Icon
            End If
        Next
        BiggestIcon.Save(MS)
        BiggestIcon.Dispose()

        Icons.Dispose()
        MS.Close()
    End Sub

End Class